#include "SceneManager.h"


SceneManager::SceneManager()
	:m_pDevice(NULL)
	,m_rootNode(std::string("Root"))
	,m_lightEffect()
	,m_vEyePosition(0,0,0)
	,m_pSpecMapRV(NULL)
{
	m_nodeMap.clear();
	D3DXMatrixIdentity(&m_matView);
	D3DXMatrixIdentity(&m_matProj);
	D3DXMatrixIdentity(&m_matWVP);

	m_rootNode.SetVisible(false);
}


SceneManager::~SceneManager(void)
{
	std::map<std::string,Node*>::const_iterator iter;
	for(iter = m_nodeMap.begin() ; iter != m_nodeMap.end() ;++iter)
	{
		if(iter->second != NULL)
			delete iter->second;
	}
}

void SceneManager::RenderOneFrame()
{


/////////////////Rendering Node/////////////////////////////////////////////////////
	UINT stride = sizeof(Vertex);
	UINT offset = 0;
	//m_pDevice->OMSetDepthStencilState(0, 0);
	m_pDevice->IASetInputLayout(m_lightEffect.GetInputLayout());
	m_pDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	m_lightEffect.SetLight(m_ParallelLight);
	m_lightEffect.SetEyePos(m_vEyePosition);

	std::map<std::string,Node*>::iterator iter = m_nodeMap.begin();
	while(iter != m_nodeMap.end())
	{
		if(iter->second->IsVisible())
		{

			iter->second->SetBuffer();
			//set effect var
			m_matWVP = iter->second->GetWorldMatrix()*m_matView*m_matProj;
			m_lightEffect.SetWVPMatrix(m_matWVP);
			m_lightEffect.SetWorldMatrix(iter->second->GetWorldMatrix());
			m_lightEffect.SetDiffuseMap(iter->second->GetAttachTexture());
			m_lightEffect.SetSpecMap(m_pSpecMapRV);
			m_lightEffect.SetTextureMatrix(iter->second->GetTextureMatrix());
			m_lightEffect.SetSpecMap(m_pSpecMapRV);


			D3D10_TECHNIQUE_DESC techDesc;
			m_lightEffect.GetEffectTech()->GetDesc(&techDesc);
			for(UINT i=0 ;i<techDesc.Passes ;++i)
			{
				m_lightEffect.GetEffectTech()->GetPassByIndex(i)->Apply(0);

				iter->second->Draw();
			}
		}
		++iter;
	}
//////////////////////////////////////////////////////////////////////////
	
}

void SceneManager::Init(ID3D10Device* device)
{
	m_pDevice = device;
	m_rootNode.SetDevice(m_pDevice);

	m_lightEffect.Init(m_pDevice);

	m_lightEffect.BuildFX();
	m_lightEffect.BuildVertexLayouts();

	m_pSpecMapRV = ResourcesManager::Instance()->GetTexture("defaultspec.dds");

////////////////init the main camera///////////////////////////////////////
	//D3DXVECTOR3	m_EyePos(0.0f,2.0f,-2.0f);
	D3DXVECTOR3	m_EyePos(0.0f,0.0f,0.0f);

	D3DXVECTOR3 target(0.0f, 0.0f, 1.0f);
	D3DXVECTOR3 right(1.0f,0.0f,0.0f);
	D3DXVECTOR3 up(0.0f,1.0f,0.0f);

	m_MainCamera.init();
	m_MainCamera.SetWorldPosition(D3DXVECTOR3(0.0f,10.0f,-10.0f));
	m_MainCamera.SetOrientation(target-m_EyePos);
	m_MainCamera.SetUpVector(up);
	m_MainCamera.UpdateViewMatrix();
//////////////////////////////////////////////////////////////////////////

	CreateParallelLight();
}

void SceneManager::SetViewMatrix( const D3DXMATRIX& matrix )
{
	m_matView = matrix;
}

void SceneManager::SetProjMatrix( const D3DXMATRIX& matrix )
{
	m_matProj = matrix;
}

void SceneManager::CreateParallelLight()
{
	//set the light
	m_ParallelLight.dir      = D3DXVECTOR3(0.707f, -0.707f, 0.0f);
	m_ParallelLight.ambient  = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f);
	m_ParallelLight.diffuse  = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
	m_ParallelLight.specular = D3DXCOLOR(0.5f, 0.4843f, 0.3f, 1.0f);
}

void SceneManager::SetEyePosition( const D3DXVECTOR3& pos )
{
	m_vEyePosition = pos;
}

Node* SceneManager::CreateNode( std::string name )
{
	std::map<std::string,Node*>::const_iterator iter;
	if(m_nodeMap.count(name))
	{
		MessageBoxA(0,"This node name has been exist!","Node Error",0);
		return NULL;
	}
	Node* ret = new Node(m_pDevice,name);

	m_nodeMap.insert(std::make_pair(name,ret));

	return ret;
}

Node* SceneManager::GetRootNode()
{
	return &m_rootNode;
}

void SceneManager::UpdateScene()
{
	SetEyePosition(m_MainCamera.GetPosition());
	SetViewMatrix(m_MainCamera.GetView());
}

Camera& SceneManager::GetMainCamera()
{
	return m_MainCamera;
}
